/**
 * @file pt_heap1.c
 * @author Linquan  
 * @brief 最简单，不允许释放内存。
 *        在程序启动时创建所需的所有任务、队列、信号量等，并在生命周期内使用，任何内容都不会删除
 *        具备确定性，不会有内存碎片，不适合真实的动态内存分配。
 *        method： 
 *          配置宏TOTAL_HEAP_SIZE，来决定堆的大小。
 *          可配置字节对齐BYTE_ALIGNMENT
 * @version 1.0
 * @date 2024-06-12
 * 
 * @copyright Copyright (c) 2024
 * 
 */

#include "FreeRTOS_heap1.h"
#if  FREE_RTOS_HEAP_1

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>


// 总共栈大小，移植敏感
#define TOTAL_HEAP_SIZE         1024
// 字节对齐，移植敏感
#define BYTE_ALIGNMENT          8
#define BYTE_ALIGNMENT_MASK     BYTE_ALIGNMENT - 1
// 指针大小，移植敏感
#ifdef __GNUC__
#define POINTER_SIZE_TYPE       uint64_t
#elif defined ARMCC_VERSION
#define POINTER_SIZE_TYPE       uint32_t
#endif

#define ADJUSTED_HEAP_SIZE      ( TOTAL_HEAP_SIZE - BYTE_ALIGNMENT )

#ifndef USE_MALLOC_FAILED_HOOK
#define USE_MALLOC_FAILED_HOOK    0
#endif

#if USE_MALLOC_FAILED_HOOK
__attribute__((weak)) void app_malloc_failed_hook( void )
{
    for (;;)
    {
        printf("ddddd\n");
    }
}
#endif

__attribute__((weak)) void heap_lock( void )
{
}

__attribute__((weak)) void heap_unlock( void )
{
}

static uint8_t s_heap[ TOTAL_HEAP_SIZE ];

static size_t s_next_free_byte = ( size_t ) 0;

void *pt_malloc(size_t size)
{
    void *ret = NULL;
    static uint8_t *aligned_heap = NULL;

    /* Ensure that blocks are always aligned. */
#if ( BYTE_ALIGNMENT != 1 )
    {
        if ( size & BYTE_ALIGNMENT_MASK ) {
            /* Byte alignment required. Check for overflow. 检查分配的空间是不是对齐的， 不是就多分配一块让他对齐*/
            if ( (size + ( BYTE_ALIGNMENT - ( size & BYTE_ALIGNMENT_MASK ) )) > size ) {
                size += ( BYTE_ALIGNMENT - ( size & BYTE_ALIGNMENT_MASK ) );
            } else {
                size = 0;
            }
        }
    }
#endif

    heap_lock();
    {
        /* 第一次分配，给分配的指针指向确定的一块区域*/
        if ( aligned_heap == NULL ) {
            /* Ensure the heap starts on a correctly aligned boundary. */
            aligned_heap = ( uint8_t * ) ( ( ( POINTER_SIZE_TYPE ) & s_heap[ BYTE_ALIGNMENT ] ) & ( ~( ( POINTER_SIZE_TYPE ) BYTE_ALIGNMENT_MASK ) ) );
        
        }

        /* Check there is enough room left for the allocation and. */
        if ( ( size > 0 ) && /* valid size */
                ( ( s_next_free_byte + size ) < ADJUSTED_HEAP_SIZE ) &&
                ( ( s_next_free_byte + size ) > s_next_free_byte ) ) { /* Check for overflow. */
            /* Return the next free byte then increment the index past this
             * block. */
            ret = aligned_heap + s_next_free_byte; /* 把当前的空闲内存分出去*/
            s_next_free_byte += size;   /* 然后把这块分出去的内存 覆盖掉*/
        }
    }
    ( void ) heap_unlock();

#if ( USE_MALLOC_FAILED_HOOK == 1 )
    {
        if ( ret == NULL ) {
            app_malloc_failed_hook();
        }
    }
#endif

    return ret;
}

void pt_free(void *pv)
{
    ( void ) pv;
}

void pt_heap_init(void)
{
    s_next_free_byte = ( size_t )0;
}

size_t pt_get_free_size(void)
{
    return( ADJUSTED_HEAP_SIZE - s_next_free_byte);
}


#endif



